home *** CD-ROM | disk | FTP | other *** search
- /*============================================================================*\
- * DrawTkl.c - mDrawMsg handler
- *
- * DrawTkl.c contains the code to process the mDrawMsg message from the Menu
- * Manager. This source file contains the routines to do ALL drawing, including
- * the scroll icons.
- \*============================================================================*/
-
-
- /******************************************************************************\
- * Header Files
- \******************************************************************************/
-
- #include <Memory.h>
- #include <Menus.h>
- #include <Resources.h>
- #include <ToolUtils.h>
- #include <Types.h>
- #include "Concordia.h"
- #include "DrawTkl.h"
- #include "SizeTkl.h"
-
-
- /******************************************************************************\
- * Constants & Macros
- \******************************************************************************/
-
- #define scrlSICNID -12288 //Resource ID of scroll arrows SICN
-
-
- /******************************************************************************\
- * Type Declarations
- \******************************************************************************/
-
- /* Small icon data */
- typedef Byte SICNData [32];
-
-
- /******************************************************************************\
- * Function Prototypes
- \******************************************************************************/
-
- void DimRect (Rect *);
- void DrawSICN (SICNData **, short, short, short);
- void DrawICON (Handle, Rect *);
-
-
- #pragma segment Main
- /******************************************************************************\
- * DoDrawMsg - Draw a menu
- *
- * DoDrawMsg draws the menu specified by TheMenu. The rectangle in global coord-
- * inates that the menu occupies is specified in MenuRect. If the system global
- * TopMenuItem is not equal to the top coordinate of MenuRect, a top scroll bar
- * is drawn. If the menu extends below the bottom of MenuRect, a bottom scroll
- * bar is drawn. The Menu Manager (I guess) sets TopMenuItem properly for pull-
- * down menus, while the popup menu tackler (DoPopupMsg) sets TopMenuItem
- * properly for popup menus. DoDrawMsg sets the system global AtMenuBottom to
- * the bottom of the entire menu, regardless of whether it fits on the screen or
- * not.
- *
- * Coding Notes
- * #A# - The sole purpose of this loop is to find the total height of the menu in
- * pixels ignoring the size of the screen. Seems like kind of a waste,
- * doesn't it?
- * #B# - The clip rectangle, MenuClip is only set if the menu has scroll icons.
- * This is determined here.
- * #C# - This loop draws each of the menu items.
- * #D# - Side-effect: system global AtMenuBottom set to coordinate of bottom of
- * Menu regardless of whether the menu fits or not.
- * #E# - We don’t need the menuEnabled bit any more so get rid of it by shifting
- * it out. Then we have to set the high bit so that all items beyond the
- * 31st will be enabled. With arithmetic right shifting, this high bit
- * will be preserved.
- \******************************************************************************/
-
- void
- DoDrawMsg (TheMenu, MenuRect)
- MenuHandle TheMenu; //=> Menu to draw >>
- Rect *MenuRect; //-> Menu's rectangle in global coords >>
- {
- Str255 *ItemString; //-> Menu item's string
- ItemInfoPtr ItemInfo; //-> Item info
- Rect ItemRect; //Item's rectangle
- Rect TotMenuRect; //Menu's rectangle w/o clipping to screen
- RgnHandle SaveClip; //=> Saved clip region
- Rect MenuClip; //Clip region of menu if menu scrolls
- long EnableFlags; //Menu's enable flags
-
- SaveClip = (RgnHandle) null;
- if ((**TheMenu).enableFlags & 1)
- {
- EnableFlags = (unsigned long) (**TheMenu).enableFlags >> 1; //#E#
- EnableFlags |= 0x80000000;
- }
- else
- EnableFlags = 0;
- SetRect (&TotMenuRect, MenuRect->left, sgTopMenuItem, MenuRect->right,
- sgTopMenuItem);
- HLock ((Handle) TheMenu);
- ItemString = (Str255 *) (**TheMenu).menuData;
- ItemString = (Str255 *) ((Byte *) ItemString + strSize (*ItemString));
- while ((*ItemString) [0] != (char) 0) //#A#
- {
- ItemInfo = (ItemInfoPtr) ((Byte *) *ItemString + strSize (*ItemString));
- TotMenuRect.bottom += CalcItemHeight (*ItemString, ItemInfo);
- ItemString = (Str255 *) (ItemInfo + 1);
- }
- HUnlock ((Handle) TheMenu);
- MenuClip = *MenuRect;
- if (TotMenuRect.top != MenuRect->top || TotMenuRect.bottom != MenuRect->
- bottom) //#B#
- {
- if (TotMenuRect.top != MenuRect->top)
- {
- DrawScroll (MenuRect, topScroll);
- MenuClip.top += scrlIconHeight;
- }
- if (TotMenuRect.bottom != MenuRect->bottom)
- {
- DrawScroll (MenuRect, botScroll);
- MenuClip.bottom -= scrlIconHeight;
- }
- SaveClip = NewRgn ();
- GetClip (SaveClip);
- ClipRect (&MenuClip);
- }
- HLock ((Handle) TheMenu);
- ItemString = (Str255 *) (**TheMenu).menuData;
- ItemString = (Str255 *) ((Byte *) ItemString + strSize (*ItemString));
- ItemRect = TotMenuRect;
- ItemRect.bottom = ItemRect.top;
- while ((*ItemString) [0] != (char) 0) //#C#
- {
- ItemInfo = (ItemInfoPtr) ((Byte *) *ItemString + strSize (*ItemString));
- ItemRect.bottom += CalcItemHeight (*ItemString, ItemInfo);
- if (ItemRect.bottom > MenuClip.top && ItemRect.top < MenuClip.bottom)
- DrawItem (*ItemString, ItemInfo, &ItemRect, (short) (EnableFlags &
- 1));
- ItemString = (Str255 *) (ItemInfo + 1);
- ItemRect.top = ItemRect.bottom;
- EnableFlags >>= 1;
- }
- HUnlock ((Handle) TheMenu);
- if (SaveClip != (RgnHandle) null)
- {
- SetClip (SaveClip);
- DisposeRgn (SaveClip);
- }
- sgAtMenuBottom = TotMenuRect.bottom; //#D#
- *((short *) ((*sgMBSaveLoc) + 16)) = 1;
- }
-
-
- #pragma segment Main
- /******************************************************************************\
- * DrawItem - Draw a menu item
- *
- * DrawItem draws a menu item whose text is specified by ItemString and whose
- * item information is specified by ItemData. The rectangle that the item
- * occupies on the screen is specified by ItemRect. If the item is enabled,
- * Enabled must be true, otherwise it must be false. DrawItem also draws mark
- * characters (like check marks); big, scaled, and disabled icons, dims items if
- * they're not enabled, and draws gray lines if the item string begins with a
- * hyphen. Any command key characters that aren't printable are ignored. If the
- * specified item icon can't be found, it is not drawn (of course), but space is
- * left for it.
- *
- * Coding Notes:
- * #A# - This calculation figures out the proper vertical coordinate to begin
- * drawing the item string so that it's centered vertically in ItemRect.
- * #B# - Draw the mark character unless this is a hierarchical menu item.
- * #C# - Draw the command-key equivalent
- * #E# - Draw the item icon
- * #F# - With these command-key equivalents, icons are half their size.
- * #G# - If couldn't load icon, ignore drawing and continue
- * #H# - With this command-key equivalent, icon is dimmed.
- * #I# - These values will be used to set the location of the item string.
- \******************************************************************************/
-
- void
- DrawItem (ItemString, ItemData, ItemRect, Enabled)
- Str255 ItemString; //Name of menu item >>
- ItemInfoPtr ItemData; //Information for menu item >>
- Rect *ItemRect; //-> Item's rectangle in screen coords >>
- short Enabled; //True if item enabled >>
- {
- short HorzPos; //Horizontal position to draw item
- short VertPos; //Vertical position to draw item
- short MarkWidth; //Width of item mark
- Handle ItemIcon; //=> Item's icon
- Rect IconRect; //Rectangle of icon
- short IconSize; //Size of icon in pixels
- FontInfo CurrFont; //Current font's characteristics
- PenState CurrPen; //Current characteristics of graphics pen
- short CurrFile; //Refnum of current resource file
- SICNData **SICNRes; //=> SICN resource
- TextStateRec TextState; //Current characteristics of text drawing
-
- GetPenState (&CurrPen);
- if (ItemString [1] == '-')
- {
- PenSize (1, 1);
- PenMode (patOr);
- PenPat (qdGlobPtr->gray);
- MoveTo (ItemRect->left, ItemRect->top + ItemRect->bottom >> 1);
- Line (ItemRect->right - ItemRect->left, 0);
- }
- else
- {
- PenMode (patOr);
- GetTextState (&TextState);
- TextFace (normal);
- TextMode (srcOr);
- GetFontInfo (&CurrFont);
- MarkWidth = CurrFont.widMax;
- if (ItemData->markChar != '\0' || ItemData->kbdEquiv != '\0')
- {
- VertPos = ((short) ((ItemRect->bottom - ItemRect->top) - (CurrFont.
- ascent + CurrFont.descent + CurrFont.leading) >> 1) +
- CurrFont.ascent + ItemRect->top); //#A#
- if (ItemData->markChar != (char) 0 && ItemData->kbdEquiv !=
- hMenuCmd) //#B#
- {
- HorzPos = ItemRect->left + itemHorzMarg;
- MoveTo (HorzPos, VertPos);
- DrawChar (ItemData->markChar);
- }
- if (ItemData->kbdEquiv > '!') //#C#
- {
- HorzPos = ItemRect->right - itemHorzMarg -
- CurrFont.widMax - CharWidth (cmmdCharCode);
- MoveTo (HorzPos, VertPos);
- DrawChar (cmmdCharCode);
- DrawChar (ItemData->kbdEquiv);
- }
- else if (ItemData->kbdEquiv == hMenuCmd)
- {
- HorzPos = ItemRect->right - sicnSize;
- VertPos = (short) ((ItemRect->bottom - ItemRect->top - (short)
- sicnSize) >> 1) + ItemRect->top;
- CurrFile = CurResFile ();
- UseResFile (0);
- if ((SICNRes = (SICNData **) Get1Resource ('SICN', scrlSICNID))
- != (SICNData **) null)
- DrawSICN (SICNRes, heirArrow, HorzPos, VertPos);
- UseResFile (CurrFile);
- }
- }
- if (ItemData->iconNum != (Byte) 0) //#E#
- {
- IconSize = iconSize;
- if (ItemData->kbdEquiv == (char) 0x1D || ItemData->kbdEquiv ==
- (char) 0x1F) //#F#
- IconSize >>= 1;
- if ((ItemIcon = GetIcon (ItemData->iconNum + 256)) != (Handle) null) //#G#
- {
- IconRect.top = (ItemRect->bottom - ItemRect->top -
- IconSize >> 1) + ItemRect->top;
- IconRect.left = ItemRect->left + itemHorzMarg + MarkWidth +
- markItemGap;
- IconRect.bottom = IconRect.top + IconSize;
- IconRect.right = IconRect.left + IconSize;
- DrawICON (ItemIcon, &IconRect);
- if (ItemData->kbdEquiv == (char) 0x1F) //#H#
- DimRect (&IconRect);
- }
- IconSize += iconItemGap; //#I#
- }
- else
- IconSize = 0; //#I#
- TextFace (ItemData->charStyle);
- GetFontInfo (&CurrFont);
- VertPos = (short) ((ItemRect->bottom - ItemRect->top) - (CurrFont.
- ascent + CurrFont.descent + CurrFont.leading) >> 1) + CurrFont.
- ascent + ItemRect->top;
- HorzPos = ItemRect->left + itemHorzMarg + MarkWidth + markItemGap +
- IconSize;
- MoveTo (HorzPos, VertPos);
- DrawString (ItemString);
- SetTextState (&TextState);
- if (! Enabled)
- DimRect (ItemRect);
- }
- SetPenState (&CurrPen);
- }
-
-
- #pragma segment Main
- /******************************************************************************\
- * DimRect - Dim a rectangle
- *
- * DimRect dims the rectangle specified by ItemRect by bit-clearing it with a
- * medium gray pattern. Normally, we could do this just by drawing over the item
- * with the standard gray pattern, but there's a problem: what if the menu has
- * scrolled an odd number of pixels and we have to draw part of a dimmed menu
- * item? We'll end up with the gray pattern that's out of phase with the part of
- * the menu item that was already drawn. To solve this, DimRect creates its own
- * pattern "on the fly" in GrayPat. Two gray patterns can be created, each one
- * being out of out of phase with the other by one pixel. The particular pattern
- * is chosen by checking to see whether the system global, TopMenuItem, is odd or
- * even. The current pen state is unchanged.
- \******************************************************************************/
-
- static void
- DimRect (TheRect)
- Rect *TheRect; //-> Rectangle to dim >>
- {
- PenState CurrPen; //Current characteristics of graphics pen
- short PatElem; //Pattern element
- short GrayPat [4]; //Gray pattern (not 8 bytes 'cause it's easier here
- short PatInd; //Index into pattern array
-
- GetPenState (&CurrPen);
- PenMode (patBic);
- if ((sgTopMenuItem & 0x0001) == 0)
- PatElem = (short) 0xAA55;
- else
- PatElem = (short) 0x55AA;
- for (PatInd = 0; PatInd < 4; PatInd++)
- GrayPat [PatInd] = PatElem;
- PenPat ((Pattern) GrayPat);
- PaintRect (TheRect);
- SetPenState (&CurrPen);
- }
-
-
- #pragma segment Main
- /******************************************************************************\
- * DrawScroll - Draw a scroll arrow
- *
- * DrawScroll draws a top scroll arrow if Which is topScroll, and it draws a
- * bottom scroll arrow if which is botScroll. The menu's rectangle must be
- * specified in MenuRect.
- \******************************************************************************/
-
- void
- DrawScroll (MenuRect, Which)
- Rect *MenuRect; //-> Menu's rectangle >>
- short Which; //topScroll=draw top arrow, botScroll=draw bottom arrow >>
- {
- SICNData **SICNRes; //=> SICN resource
- short HorzPos; //Horizontal position of icon
- short VertPos; //Vertical position of icon
- Rect ScrlRect; //Rectangle of scroll icon area
- PenState CurrPen; //Current pen state
- short CurrFile; //Current resource file's refnum
-
- HorzPos = (short) ((MenuRect->right - MenuRect->left - sicnSize) >> 1) +
- MenuRect->left;
- ScrlRect = *MenuRect;
- GetPenState (&CurrPen);
- PenPat (qdGlobPtr->black);
- PenMode (patCopy);
- PenSize (1, 1);
- if (Which == topScroll)
- {
- ScrlRect.bottom = ScrlRect.top + scrlIconHeight;
- EraseRect (&ScrlRect);
- MoveTo (MenuRect->left, MenuRect->top + scrlIconHeight - 1);
- Line (MenuRect->right - MenuRect->left, 0);
- VertPos = MenuRect->top + 1;
- }
- else
- {
- ScrlRect.top = ScrlRect.bottom - scrlIconHeight;
- EraseRect (&ScrlRect);
- MoveTo (MenuRect->left, MenuRect->bottom - scrlIconHeight);
- Line (MenuRect->right - MenuRect->left, 0);
- VertPos = MenuRect->bottom - 1 - sicnSize;
- }
- PenMode (patOr);
- CurrFile = CurResFile ();
- UseResFile (0);
- if ((SICNRes = (SICNData **) Get1Resource ('SICN', scrlSICNID)) !=
- (SICNData **) null)
- DrawSICN (SICNRes, Which, HorzPos, VertPos);
- UseResFile (CurrFile);
- SetPenState (&CurrPen);
- }
-
-
- #pragma segment Main
- /******************************************************************************\
- * DrawSICN - Draw a small icon
- *
- * DrawSICN draws the small icon specified by TheIcon into the current port.
- * Each SICNData can hold any number of SICNs, so Index specifies which SICN to
- * draw, 0 specifying the first. HorzPos and VertPos specify the horizontal and
- * vertical position to draw the top-left corner of the icon in local
- * coordinates. If TheIcon doesn't specify a SICN or if Index is out of range,
- * garbage will be drawn. The transfer mode will be the equivalent of the
- * current pen mode of the current port. For example, if the current pen mode is
- * patXor, the SICN will be drawn in srcXor mode.
- \******************************************************************************/
-
- static void
- DrawSICN (TheIcon, Index, HorzPos, VertPos)
- SICNData **TheIcon; //=> Icon data >>
- short Index; //Index of icon to draw >>
- short HorzPos; //Horizontal position of left edge of icon >>
- short VertPos; //Vertical position of top edge of icon >>
- {
- BitMap IconBits; //Bitmap for icon
- GrafPtr CurrPort; //-> Current GrafPort
- Rect SICNRect; //Rectangle to draw icon into
- short TransMode; //Transfer mode to use
-
- HLock ((Handle) TheIcon);
- SetRect (&IconBits.bounds, 0, 0, sicnSize, sicnSize);
- IconBits.rowBytes = 2;
- IconBits.baseAddr = (Ptr) (*TheIcon + Index);
- SetRect (&SICNRect, HorzPos, VertPos, HorzPos + sicnSize, VertPos +
- sicnSize);
- GetPort (&CurrPort);
- if (CurrPort->pnMode == patCopy || CurrPort->pnMode == notPatCopy)
- TransMode = srcCopy;
- else if (CurrPort->pnMode == patOr || CurrPort->pnMode == notPatOr)
- TransMode = srcOr;
- else if (CurrPort->pnMode == patXor || CurrPort->pnMode == notPatXor)
- TransMode = srcXor;
- else if (CurrPort->pnMode == patBic || CurrPort->pnMode == notPatBic)
- TransMode = srcBic;
- CopyBits (&IconBits, &CurrPort->portBits, &IconBits.bounds, &SICNRect,
- TransMode, (RgnHandle) null);
- HUnlock ((Handle) TheIcon);
- }
-
-
- #pragma segment Main
- /******************************************************************************\
- * DrawICON - Draw an icon
- *
- * DrawICON draws the icon specified by TheIcon into the current port. IconRect
- * specifies the size and location to draw the icon in local coordinates. If
- * TheIcon doesn't specify an ICON, garbage will be drawn. The transfer mode
- * will be the equivalent of the current pen mode of the current port. For
- * example, if the current pen mode is patXor, the ICON will be drawn in srcXor
- * mode.
- \******************************************************************************/
-
- static void
- DrawICON (TheIcon, IconRect)
- Handle TheIcon; //=> Icon data >>
- Rect *IconRect; //-> Rectangle to draw icon into >>
- {
- BitMap IconBits; //Bitmap for icon
- GrafPtr CurrPort; //-> Current GrafPort
- short TransMode; //Transfer mode to use
-
- HLock (TheIcon);
- SetRect (&IconBits.bounds, 0, 0, iconSize, iconSize);
- IconBits.rowBytes = 4;
- IconBits.baseAddr = *TheIcon;
- GetPort (&CurrPort);
- if (CurrPort->pnMode == patCopy || CurrPort->pnMode == notPatCopy)
- TransMode = srcCopy;
- else if (CurrPort->pnMode == patOr || CurrPort->pnMode == notPatOr)
- TransMode = srcOr;
- else if (CurrPort->pnMode == patXor || CurrPort->pnMode == notPatXor)
- TransMode = srcXor;
- else if (CurrPort->pnMode == patBic || CurrPort->pnMode == notPatBic)
- TransMode = srcBic;
- CopyBits (&IconBits, &CurrPort->portBits, &IconBits.bounds, IconRect,
- TransMode, (RgnHandle) null);
- HUnlock (TheIcon);
- }
-